#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<fcntl.h>

int conn_ser();
char*get_cmd(char buff[],char*myargv[]);

void recv_file(int c,char*s,char*filename)
{
    if(filename==NULL||s==NULL)
    {
        return ;
    }
    send(c,s,strlen(s),0);

    char buff[128]={0};
    int n=recv(c,buff,127,0);
    if(n<=0)
    {
        printf("ser close\n");
        return ;
    }

    if(strncmp(buff,"ok#",3)!=0)
    {
        printf("文件不存在或无法下载\n");
        return;
    }
    
    int filesize=atoi(buff+3);//ok#0
    int fd=open(filename,O_WRONLY|O_CREAT,0600);
    if(filesize==0)
    {
        send(c,"err",3,0);
        close(fd);
        return ;
    }
    if(fd==-1)
    {
        send(c,"err",3,0);
        return ;
    }
    send(c,"ok",2,0);

    //循环接收数据
    int curr_size=0;//当前累加的数据总数目
    float f=0.0;//计算百分比
    int num=0;
    char data[1024]={0};
    while(1)
    {
        num=recv(c,data,1024,0);
        if(num<=0)
        {
            printf("服务器关闭\n");
            break;
        }

        write(fd,data,num);
        curr_size+=num;
        f=curr_size*100.0/filesize;
        printf("down %s :%.1f%%\r",filename,f);
        fflush(stdout);

        if(curr_size>=filesize)
        {
            break;
        }

    }
    printf("\n");
    close(fd);

}

void send_file(int c,char * s,char*filename)
{
    if(filename==NULL||s==NULL)
    {
         printf("输入文件名字无效\n");
         return;
    }
    send(c,s,strlen(s),0);
    int fd=open(filename,O_RDONLY);
    if(fd==-1)
    {
        printf("打开文件失败\n");
        return ;
    }

    printf("打开文件成功\n");
    int filesize=lseek(fd,0,SEEK_END);
    lseek(fd,0,SEEK_SET);
    printf("获取文件大小：%d\n",filesize);
    
    char buff[128]={0};
    sprintf(buff,"ok#%d",filesize);
    send(c,buff,strlen(buff),0);
    printf("发送文件大小成功\n");

    memset(buff,0,128);

    int n=recv(c,buff,127,0);
    printf("接收服务器数据成功\n");
    if(n<=0)
    {
        close(fd);
        return ;
    }
    if(strncmp(buff,"ok",2)!=0)
    {
        close(fd);
        return ;
    }

    int curr_size=0;
    float f=0.0;
    char data[1024]={0};
    int num=0;
    while((num=read(fd,data,1024))>0)
    {
        send(c,data,num,0);
        curr_size+=num;
        f=curr_size*100.0/filesize;
        printf("up %s :%.1f%%\r",filename,f);
        fflush(stdout);
    }
    close(fd);
    printf("up file finish\n");
}

int main()
{
    //连接到服务器
    int sockfd=conn_ser();
    if(sockfd==-1)
    {
        printf("connect ser failed\n");
        exit(0);
    }

    //从键盘接收数据，将数据发送给服务器
    while(1)
    {
        char buff[128]={0};
        printf("connect 127.0.0.1>>");
        fflush(stdout);
        fgets(buff,128,stdin);//"ls\n"
        buff[strlen(buff)-1]=0;//把最后一个换行字符改为字符串结束符‘\0’  "ls"
        char send_buff[128]={0};//备份一份给服务器发送
        strcpy(send_buff,buff);

        char *myargv[10]={0};//存放解析的命令和参数
        char* cmd=get_cmd(buff,myargv);

        if(cmd==NULL)
        {
            continue;
        }

        if(strcmp(cmd,"end")==0)
        {
            break;
        }
        else if(strcmp(cmd,"get")==0)
        {
            //下载
            recv_file(sockfd,send_buff,myargv[1]);
        }
        else if(strcmp(cmd,"up")==0)
        {
            //客户端想上传
            send_file(sockfd,send_buff,myargv[1]);
        }
        else//和服务器交互的命令
        {
            send(sockfd,send_buff,strlen(send_buff),0);
             //接收服务器的回复信息
            char recv_buff[1024]={0};
            int res=recv(sockfd,recv_buff,1023,0);//"ok#"
            if(res<=0)
            {
                printf("ser close\n");
                break;
            }
            if(strncmp(recv_buff,"ok#",3)==0)
            {
                printf("%s\n",recv_buff+3);
            }
            else
            {
                printf("cmd run err\n");
            }

        }

    }
    close(sockfd);

}

char * get_cmd(char buff[],char *myargv[])
{
    if(buff==NULL||myargv==NULL)
    {
        return NULL;
    }
    int i=0;
    char *s=strtok(buff," ");
    while(s!=NULL)
    {
        myargv[i++]=s;
        s=strtok(NULL," ");
    }
    return myargv[0];
}

int conn_ser()
{
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        return -1;
    }
    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(6000);
    saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

    int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    if(res==-1)
    {
        return -1;
    }
    return sockfd;
}
